package com.zhs.base.service;


import cn.hutool.core.lang.Assert;
import cn.hutool.core.util.RandomUtil;
import com.zhs.base.dto.GeoCodeDto;
import com.zhs.base.dto.GeoInfoDto;
import com.zhs.base.loadbalance.SmoothWeightPolling;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;
import java.util.*;


/**
 * @author Java架构师之旅
 * @version 1.0
 * @date 2022年08月16日 17:21.
 * 个人免费版支持qps=65
 * @apiNote 注意：fastjson 版本在2.0.07以上方可使用
 * <a href="https://lbsyun.baidu.com/index.php?title=webapi/guide/webservice-geocoding">百度文档</a>
 * <a href="https://lbs.amap.com/api/webservice/guide/api/georegeo/#geo_list">高德文档</a>
 * <a href="https://lbs.qq.com/service/webService/webServiceGuide/webServiceGcoder">腾讯文档</a>
 */
@Component
public class MapApiManager {
    // 负载均衡支持平滑加权轮询(polling)、随机(random)。默认平滑加权轮询
    private static final List<String> BALANCE_TYPE = Arrays.asList("polling", "random");
    public static final Map<MapApiService, Integer> WEIGHT_LIST = new LinkedHashMap<>();
    @Autowired(required = false)
    List<MapApiService> mapApiServiceList;

    @Value("${map.balance.type:polling}")
    private String balanceType;

    @PostConstruct
    public void init() {
        mapApiServiceList.removeIf(Objects::isNull);
        if (Objects.equals(BALANCE_TYPE.get(0), balanceType)) {
            if (WEIGHT_LIST.isEmpty()) {
                mapApiServiceList.forEach(k -> {
                    WEIGHT_LIST.put(k, k.getWeight());
                });
            }
        }
    }

    private synchronized MapApiService getMapApiService() {
        Assert.notEmpty(mapApiServiceList, "NO SERVICE AVAILABLE.");
        if (Objects.equals(BALANCE_TYPE.get(1), balanceType)) {
            return mapApiServiceList.get(RandomUtil.randomInt(0, mapApiServiceList.size()));
        } else {
            return SmoothWeightPolling.getMapApiService(WEIGHT_LIST);
        }
    }

    public GeoCodeDto getGeocode(String address) {
        if (StringUtils.isBlank(address)) throw new IllegalArgumentException("ADDRESS CANNOT BE BLANK.");
        GeoCodeDto geoCodeDto = getMapApiService().getGeocode(address);
        if (null == geoCodeDto) {
            // 失败换其他的再试一次
            geoCodeDto = getMapApiService().getGeocode(address);
            if (null == geoCodeDto) {
                // 失败换其他的再试一次
                geoCodeDto = getMapApiService().getGeocode(address);
            }
        }
        return geoCodeDto;
    }

    public GeoInfoDto getAddress(GeoCodeDto geoCodeDto) {
        if (null == geoCodeDto || StringUtils.isBlank(geoCodeDto.getLng()) || StringUtils.isBlank(geoCodeDto.getLat())){
            throw new IllegalArgumentException("LNG AND LAT CANNOT BE BLANK.");
        }
        GeoInfoDto geoInfoDto = getMapApiService().getAddress(geoCodeDto);
        if (null == geoInfoDto) {
            // 失败换其他的再试一次
            geoInfoDto = getMapApiService().getAddress(geoCodeDto);
            if (null == geoInfoDto) {
                // 失败换其他的再试一次
                geoInfoDto = getMapApiService().getAddress(geoCodeDto);
            }
        }
        return geoInfoDto;
    }

}
